import { ref, onUnmounted } from "vue";
import { getToken } from "@/utils/auth";
// WebSocket 封装类
class WebSocketClient {
  constructor(url, options = {}) {
    this.url = `${url}?token=${getToken()}`;
    this.opts = {
      heartbeatInterval: 30000,
      reconnectInterval: 5000,
      maxReconnectAttempts: 5,
      heartbeatMessage: JSON.stringify({ event: "ping" }), // 心跳消息默认值
      ...options,
    };

    this.ws = null;
    this.reconnectAttempts = 0;
    this.listeners = {};
    this.heartbeatInterval = null;
    this.messageQueue = [];
    this.manualClose = false; // 标识是否为手动关闭
    this.connect();
  }

  // 初始化 WebSocket 连接
  connect() {
    this.ws = new WebSocket(this.url);
    this.ws.onopen = this.handleOpen.bind(this);
    this.ws.onmessage = this.handleMessage.bind(this);
    this.ws.onerror = this.handleError.bind(this);
    this.ws.onclose = this.handleClose.bind(this);
  }

  // 处理 WebSocket 打开事件
  handleOpen(event) {
    console.log("WebSocket connected:", event);
    this.reconnectAttempts = 0;
    this.startHeartbeat();
    this.emit("open", event);
    this.flushMessageQueue();
  }

  // 处理 WebSocket 消息事件
  handleMessage(event) {
    console.log("WebSocket message received:", event.data);
    this.emit("message", event.data);
  }

  // 处理 WebSocket 错误事件
  handleError(event) {
    console.error("WebSocket error:", event);
    this.emit("error", event);
  }

  // 处理 WebSocket 关闭事件
  handleClose(event) {
    console.log("WebSocket closed:", event);
    this.stopHeartbeat();
    this.emit("close", event);

    // 如果不是手动关闭，则尝试重连
    if (!this.manualClose) {
      this.reconnect();
    }
  }

  // 开始心跳
  startHeartbeat() {
    if (!this.opts.heartbeatInterval) return;
    this.heartbeatInterval = setInterval(() => {
      if (this.ws && this.ws.readyState === WebSocket.OPEN) {
        this.ws.send(this.opts.heartbeatMessage);
      }
    }, this.opts.heartbeatInterval);
  }

  // 停止心跳
  stopHeartbeat() {
    if (this.heartbeatInterval) {
      clearInterval(this.heartbeatInterval);
      this.heartbeatInterval = null;
    }
  }

  // 重连逻辑
  reconnect() {
    if (this.reconnectAttempts < this.opts.maxReconnectAttempts) {
      setTimeout(() => {
        this.reconnectAttempts++;
        this.connect();
      }, this.opts.reconnectInterval);
    }
  }

  // 刷新消息队列
  flushMessageQueue() {
    while (this.messageQueue.length > 0) {
      this.send(this.messageQueue.shift());
    }
  }

  // 发送消息
  send(data) {
    if (this.ws && this.ws.readyState === WebSocket.OPEN) {
      this.ws.send(data);
    } else {
      console.error("WebSocket is not open. Queueing message:", data);
      this.messageQueue.push(data);
    }
  }

  // 关闭 WebSocket 连接
  close(manual = false) {
    console.log("Attempting to close WebSocket");
    this.manualClose = manual;
    if (this.ws) {
      if (this.ws.readyState === WebSocket.OPEN) {
        this.ws.close();
        console.log("WebSocket close() called");
      } else if (this.ws.readyState === WebSocket.CLOSING) {
        console.log("WebSocket is already closing");
      } else if (this.ws.readyState === WebSocket.CLOSED) {
        console.log("WebSocket is already closed");
      }
      this.ws = null;
    }
  }

  // 添加事件监听器
  on(event, callback) {
    if (!this.listeners[event]) {
      this.listeners[event] = [];
    }
    this.listeners[event].push(callback);
  }

  // 移除事件监听器
  off(event, callback) {
    if (!this.listeners[event]) return;
    if (callback) {
      this.listeners[event] = this.listeners[event].filter(
        (cb) => cb !== callback
      );
    } else {
      delete this.listeners[event];
    }
  }

  // 触发事件
  emit(event, data) {
    if (this.listeners[event]) {
      this.listeners[event].forEach((callback) => callback(data));
    }
  }
}

// 使用 WebSocket 的组合式 API
export function useWebSocket(url, options) {
  const webSocketClient = new WebSocketClient(url, options);

  const cleanupWebSocket = (manual = false) => {
    webSocketClient.off("open");
    webSocketClient.off("message");
    webSocketClient.off("error");
    webSocketClient.off("close");
    webSocketClient.close(manual);
  };

  onUnmounted(() => {
    cleanupWebSocket();
  });

  return {
    socket: webSocketClient,
    send: webSocketClient.send.bind(webSocketClient),
    on: webSocketClient.on.bind(webSocketClient),
    off: webSocketClient.off.bind(webSocketClient),
    cleanup: cleanupWebSocket,
  };
}